/**
 * 
 */
package perceptron;

import java.io.IOException;
import java.util.ArrayList;

/**
 * Cette classe permet de gérer le chargement de plusieurs classifiers.
 * Il charge au maximum un certain nombre de classifier en ram. Si il a besoin d'en charger un autre, il remplace celui qui est resté le plus longtemps sans être appelé.
 * @author simon
 */
public class ClassifiersBuffer {
	
	/**
	 * Nombre maximum de classifieurs en ram.
	 */
	private int maxClass ; 
	
	/**
	 * La liste des classifieurs chargés.
	 */
	private ArrayList<Classifier> classifiers ;
	
	/**
	 * La listes des INDICES (dans la liste paths) des classifieurs chargés.
	 */
	private ArrayList<Integer> loaded ;
	
	/**
	 * Liste des emplacement des classifiers connus.
	 */
	private ArrayList<String> paths ;
	
	/**
	 * Liste des temps écoulés depuis la dernière utilisation des classifieurs chargés.
	 */
	private int[] durations ;
	
	/**
	 * Constructeur.
	 */
	public ClassifiersBuffer(int maxClass, String[] paths) {
		
		this.maxClass=maxClass ;
		
		this.paths=new ArrayList<String>(paths.length) ;
		for(int i=0 ; i<paths.length ; i++) {
			this.paths.add(paths[i]) ;
		}
		
		this.classifiers = new ArrayList<Classifier>(maxClass) ;
		
		this.loaded=new ArrayList<Integer>(maxClass) ;
		
		this.durations= new int[maxClass] ;
		for(int i = 0 ; i<maxClass ; i++) {
			this.durations[i] = 0 ;
		}
		
	}
	
	/**
	 * Retourner le i-eme classifieur.
	 * @throws IOException 
	 */
	public Classifier getClassifier(int i) throws IOException {
		
		/* Mise à jour des durée */
		for(int j = 0 ; j<loaded.size() ; j++) {
			if(loaded.get(j)==i)
				this.durations[j]=0 ;
			else
				this.durations[j]++ ;	
		}
		
		/* Cas où le classifieur est déjà chargé en mémoire */
		if(loaded.contains(i)) {
			System.out.println(11111);
			System.out.println(loaded);
			System.out.println(durations);
			return classifiers.get(loaded.indexOf(i)) ;
		}
		
		/* Cas où le classifieur n'est pas déjà en mémoire,
		 * mais que le nombre max de classifieurs n'est pas atteint.
		 */
		else if(loaded.size()<maxClass) {
			/* Charger ce classifieur */
			classifiers.add(ClassifierLoader.load(paths.get(i))) ;
			System.out.println(paths.get(i));
			loaded.add(i) ;
			System.out.println(22222);
			System.out.println(loaded);
			System.out.println(durations);
			return classifiers.get(loaded.indexOf(i)) ;
		}
		
		/* Cas où le classifieur n'est pas déjà en mémoire,
		 * mais que le nombre max de classifieurs est atteint.
		 */
		else {
			/* Il faut trouver quelle classifeur ecraser. */
			int toErase = 0 ;
			for(int j=1 ; j<maxClass ; j++) {
				if (durations[j]>durations[toErase])
					toErase=j ;
			}
			classifiers.set(toErase,ClassifierLoader.load(paths.get(i))) ;
			loaded.set(toErase,i) ;
			this.durations[toErase]=0 ;
			System.out.println(33333);
			System.out.println(loaded);
			System.out.println(durations);
			return classifiers.get(loaded.indexOf(i)) ;
		}
		
	}
	
	
	/**
	 * TESTS
	 */
	public static void main(String[] args) {
		
		ClassifiersBuffer b = new ClassifiersBuffer(3,new String[]{"data/short/per0","data/short/per1","data/short/per2","data/short/per3","data/short/per4"}) ; 
		try {
			System.out.println(b.getClassifier(0).getName());
			System.out.println("");
			System.out.println(b.getClassifier(1).getName());
			System.out.println("");
			System.out.println(b.getClassifier(2).getName());
			System.out.println("");
			System.out.println(b.getClassifier(3).getName());
			System.out.println("");
			System.out.println(b.getClassifier(4).getName());
			System.out.println("");
			System.out.println(b.getClassifier(4).getName());
			System.out.println("");
			System.out.println(b.getClassifier(0).getName());
			System.out.println("");
			System.out.println(b.getClassifier(2).getName());
			System.out.println("");
			System.out.println(b.getClassifier(3).getName());
			System.out.println("");
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	

}
